
#include <stdint.h>
#include "../gba_dma.h"
#include "../fe8.h"
#include "mareeta.h"
#define draw_pal evel_pal
#define draw_tile evel_tile
#define linepal evel_linepal
#include "evel.h"
#undef draw_pal     //evel_pal
#undef draw_tile    //evel_tile
#undef linepal      //evel_linepal

//实时更新TILE
//原来出BUG的原因找到了，是因为每次执行h80054C5(每帧都执行)，都会重新生成tile数据,CPU在80054C5损耗过高
#define UPDATE_TILE 0

#define nasm(s) asm(s); asm("\n");

#define oam_att0_color256       (1<<13)
#define oam_att0_square         (0<<14)
#define oam_att0_horizon        (1<<14)
#define oam_att0_vertical       (2<<14)
#define oam_att0_prohibited     (3<<14)
#define oam_att0_mosaic         (1<<12)

#define oam_att1_hflip          (1<<12)
#define oam_att1_vflip          (1<<13)
#define oam_att1_size8          (0<<14)
#define oam_att1_size16          (1<<14)
#define oam_att1_size32          (2<<14)
#define oam_att1_size64          (3<<14)

#define oam_att2_priority(v)    ((v)<<10)
#define oam_att2_color16(v)     ((v)<<12)

//#define TEST 2

#ifndef TEST
#define TEST 1
#endif

#if TEST

typedef void (*drawfunc)();

typedef struct{
    uint8_t     *palbase;
    uint8_t     **draw_linepal;
    uint8_t     *tile;
    uint8_t     *dest_pal;
    uint8_t     *dest_vram;
    drawfunc    func;
}hblank_draw_t;

typedef struct{
    uint32_t    pal_addr;
    uint32_t    pal_src;
    int16_t     pal_num;
}hblank_draw_line_t;

typedef struct{
    int count;
    int16_t     initd;
    hblank_draw_line_t  lines[80];
    hblank_draw_t draw[4]; //4个头像
    uint8_t             exec[0];
}hblank_funcproc;
inline static int hblank_draw_tile(hblank_draw_t *d,int varmy,int tiley){
    if(d->tile){
        gba_memcpy(d->dest_vram+varmy*0x400,d->tile + tiley*8*0x40,8*0x40);
    }
}

#define gba_memcpy(d,s,size) DMA_Copy(3,s,d,DMA_HBLANK|DMA32 | ((size)>>2))
inline static int hblank_draw_tile_dma(hblank_draw_t *d,int varmy,int tiley){
    if(d->tile){
        gba_memcpy(d->dest_vram+varmy*0x400,d->tile + tiley*8*0x40,8*0x40);
    }
}
#undef gba_memcpy

inline static int hblank_draw_pal(hblank_draw_t *d,int line){
    if(d->draw_linepal||1){
        //
        if(d->draw_linepal[line]){
            gba_memcpy(d->dest_pal,d->draw_linepal[line],64*0x2); //64色
        }
    }
}

#define gba_memcpy(d,s,size) DMA_Copy(3,s,d,DMA_HBLANK|DMA32 | ((size)>>2))
inline static int hblank_draw_pal_dma(hblank_draw_t *d,int line){
    line += 1;
    if(d->draw_linepal||1){
        //
        if(d->draw_linepal[line]){
            gba_memcpy(d->dest_pal,d->draw_linepal[line],64*0x2); //64色
        }
    }
}
#undef gba_memcpy

hblank_funcproc * const hblank_proc = (void*)0x201e000;
#endif


const uint16_t oam_att[] = {
    //长度
    //(sizeof(oam_att)>>2),
    #if 0
    1,
    oam_att0_square|oam_att0_color256, //正方形256色
    oam_att1_size64/*|oam_att1_hflip*/|0x1e0,
    0,
    #else

    #if 0
    //以32x16显示
    8,
    oam_att0_horizon|oam_att0_color256, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0,
    oam_att0_horizon|oam_att0_color256, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    8,
    oam_att0_horizon|oam_att0_color256 + 1*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    1*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 1*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    1*0x40+8,
    oam_att0_horizon|oam_att0_color256 + 2*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    2*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 2*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    2*0x40+8,
    oam_att0_horizon|oam_att0_color256 + 3*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    3*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 3*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    3*0x40+8,
    #elif 0
    10,
    oam_att0_horizon|oam_att0_color256, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0,
    oam_att0_horizon|oam_att0_color256, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    8,
    oam_att0_horizon|oam_att0_color256 + 1*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 1*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    0*0x40+8,
    oam_att0_horizon|oam_att0_color256 + 2*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 2*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    0*0x40+8,
    oam_att0_horizon|oam_att0_color256 + 3*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 3*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    0*0x40+8,

    oam_att0_horizon|oam_att0_color256 + 4*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0*0x40+0,
    oam_att0_horizon|oam_att0_color256 + 4*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    0*0x40+8,
    #else
        //以32x16显示
    8,
    oam_att0_horizon|oam_att0_color256, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0,
    oam_att0_horizon|oam_att0_color256, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    8,
    oam_att0_horizon|oam_att0_color256 + 1*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    16,
    oam_att0_horizon|oam_att0_color256 + 1*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    24,
    oam_att0_horizon|oam_att0_color256 + 2*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0x40+0,
    oam_att0_horizon|oam_att0_color256 + 2*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    0x40+8,
    oam_att0_horizon|oam_att0_color256 + 3*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0,
    0x40+16,
    oam_att0_horizon|oam_att0_color256 + 3*16, //正方形256色
    oam_att1_size32/*|oam_att1_hflip*/|0x1e0+32,
    0x40+24,
    #endif


    #endif
};



//tile层数据
void h800549D(uint32_t r0){
    CALLT(0x800549C,r0);
    int id = geth(r0+0x3e);//获得角色id
    if(id==0x6b){
        //士兵的ID
        int offset = getb(r0+0x40);
        offset *= 8;
        offset += 0x202A688;
        offset = get(offset);
        offset += 0x6010000;
        uint8_t *tile = offset;
        int y;
        for(y=0;y<8;y++){
            //gba_memcpy(tile+0x400*y,draw_tile+y*8*0x40,8*0x40);
        }
    }
    else if(id==0x2c){
        //塔娜的id
    }
}

inline static void hblank_drawl(int line,int idx){
    if(line==60){
        hblank_draw_tile(hblank_proc->draw+idx,0,0);
        hblank_draw_tile(hblank_proc->draw+idx,1,1);
    }
    if(line>=80){
        line -= 80;
        if(line<=72){
            //if(idx==0){
                hblank_draw_pal(hblank_proc->draw+idx,line);
            //}
            if((line&0xf)==13){
                int y = line/8;
                y += 1;
                hblank_draw_tile(hblank_proc->draw+idx,0,y);
            }
            else if((line&0xf)==5){
                int y = line/8;
                y += 1;
                hblank_draw_tile(hblank_proc->draw+idx,1,y);
            }
        }
    }
}

static void hblank_draw0(){
    int line = REG_VCOUNT;
    line += 1;
    hblank_drawl(line,0);
}

static void hblank_draw1(){
    int line = REG_VCOUNT;
    line += 1;
    hblank_drawl(line,1);
}

static void hblank_draw2(){
    int line = REG_VCOUNT;
    line += 1;
    hblank_drawl(line,2);
}

static void hblank_draw3(){
    int line = REG_VCOUNT;
    line += 1;
    hblank_drawl(line,3);
}

static void hblank(){
    int line = REG_VCOUNT;
    line += 1;
    //(*(int*)0x200f000) ++;
#if UPDATE_TILE
    if(line==60){
        hblank_draw_tile(hblank_proc->draw+0,0,0);
        hblank_draw_tile(hblank_proc->draw+0,1,1);
        hblank_draw_tile(hblank_proc->draw+1,0,0);
        hblank_draw_tile(hblank_proc->draw+1,1,1);
    }
#endif
    if(line>=80){
        //更新调色板
        line -= 80;


        if(line==73){
        }
        if(line<=72){

            #define gba_memcpy(d,s,size) DMA_Copy(3,s,d,/*DMA_HBLANK|*/DMA32 | ((size)>>2))
            #define FAST_DMA_VRAM 1
            //使用DMA_Copy  缓存复制 最多可显示三个头像，不过有细微显示异常
            #if 0
            hblank_draw_t *draw = &hblank_proc->draw[0];
            if(draw->draw_linepal[line]){
                gba_memcpy(0x05000000+0x200,
                #if FAST_DMA_VRAM
                0x0600d000+
                (uint8_t*)draw->draw_linepal[line] - draw->palbase
                #else
                draw->draw_linepal[line]
                #endif
                ,64*2);
            }
            #else
            hblank_draw_line_t *draw_line = hblank_proc->lines+line;
            if(draw_line->pal_addr){
                gba_memcpy(draw_line->pal_addr,
                draw_line->pal_src
                ,draw_line->pal_num);
            }
            #endif
            #undef gba_memcpy

            #if UPDATE_TILE
            int liney = line&0xf;
            if(liney==14){
                int y = line/8;
                y += 1;
                hblank_draw_tile(hblank_proc->draw+0,0,y);
                hblank_draw_tile(hblank_proc->draw+1,0,y);
            }
            else if(liney==6){
                int y = line/8;
                y += 1;
                hblank_draw_tile(hblank_proc->draw+0,1,y);
                hblank_draw_tile(hblank_proc->draw+1,1,y);
            }
            #endif

        }
    }
}

extern void hblank_end();

void h80054C5(uint32_t r0){
    uint32_t event = r0;
    if((CALLT(0x80056AC,r0)&0x4000)){
        //关闭？
        hblank_proc->count++;
    }
    int id = geth(event+0x3e);//获得角色id
    //需要在80054C4 重新设置oam属性，否则对话时，口型会出现16色
       if(id==0x2c||id==0x6b){
        uint16_t v1 = geth(event+0x30) & 0x807;
        switch (v1)
        {
        case 3:{
            //头像朝向右边
            //设置64色
            str(event+0x38,oam_att);
            //202515c
        }
        break;
        case 2:{
            str(event+0x38,oam_att);
            //朝左
        }
        break;
        default:
            break;
        }
       }

    //会实时更新精灵数据
    CALLT(0x80054C4,r0);
    //202515c

    //这个会设置包括嘴型


    #if !NHACK
        //重新设置精灵的数据
        //a5 为位置

        /*
        0:为小框头像，64*72,正常情况下是72*72,  头像朝左面向
        1:同上, 不过头像朝右面向
        2:头像朝左面向
        3:头像朝右面向
        4:朝左,72*64
        5:朝右,72*64
        6:错误
            &0x2000 未知
            &0x1000 未知

        */



    //    if(id!=0x6b){
    //        return event;
    //    }
    irqEnable(IRQ_HBLANK);

    if(id==0x6b&&(hblank_proc->initd&1)){
        return;
    }
    if(id==0x2c&&(hblank_proc->initd&2)){
        return;
    }


    if(id==0x2c){
        hblank_proc->initd |= 2;
    }
    if(id==0x6b){
        hblank_proc->initd |= 1;
    }

    int offset = getb(r0+0x40);
    offset *= 8;
    offset += 0x202A688;
    offset = get(offset);
    offset += 0x6010000;
    uint8_t *tile = offset;
    uint8_t *d_tile = draw_tile;
    uint8_t **d_linepal = linepal;
    uint8_t *d_pal = draw_pal;
    if(tile==0x06001600){
        hblank_proc->initd |= 0x10;
    }
    else if(tile==0x06001500){
        hblank_proc->initd |= 0x20;
    }
    else if(tile==0x06001400){
        hblank_proc->initd |= 0x40;
    }
    else if(tile==0x06001300){
        hblank_proc->initd |= 0x80;
    }
    if(!(id==0x6b||id==0x2c)){
        gba_memset(hblank_proc,0,sizeof(*hblank_proc));
    }

    if(id==0x6b||id==0x2c){
        //士兵的ID


        if(id==0x2c){
            d_tile = evel_tile;
            d_pal = evel_pal;
            d_linepal = evel_linepal;
        }
        int y;
        #if 0
        for(y=0;y<8;y+=1){
            //32x16 显示精灵，则32为4个tile,每个tile为0x40字节
            gba_memcpy(tile+0x400*y,draw_tile+y*8*0x40,8*0x40);
        }
        #else

        for(y=0;y<8;y+=2){
            //32x16 显示精灵，则32为4个tile,每个tile为0x40字节
            int offset = y>>1;
            offset &= 1; //
            int line = y>>2;
            gba_memcpy(tile+0x400*0+
            offset*0x200 + line*0x800
            ,d_tile +y*8*0x40,8*0x40);

            //y += 1;

            gba_memcpy(tile+0x400*1+
            offset*0x200+ line*0x800
            ,d_tile +(y+1)*8*0x40,8*0x40);
        }

        if(id==0x2c){
            int i;


            for(i=0;i<0x1000;i+=8){
                uint64_t *tile8 = (uint64_t*)(tile+i);
                uint64_t add = 0;
                uint64_t v = *tile8;
                int off;
                for(off=0;off<8;off++){
                    if((v&((uint64_t)0xff<<off*8))){
                        add |= (uint64_t)0x40<<off*8;
                    }
                }
                *tile8 += add;
            }

            // for(i=0;i<0x1000;i++){
            //     if(tile[i]!=0){
            //         tile[i] += 0x40;
            //     }
            // }
        }
        //hblank_proc->count ++;

        #endif


        if(id==0x6b){
            hblank_proc->draw[0].palbase =          draw_pal;
            hblank_proc->draw[0].draw_linepal    =  linepal;
            hblank_proc->draw[0].tile       =       d_tile;
            hblank_proc->draw[0].dest_vram  =       tile;
            //复制到显存中，这样dma性能才更好
            // #if FAST_DMA_VRAM
            // gba_memcpy(0x0600d000,draw_pal,sizeof(draw_pal));
            // #endif
            hblank_proc->draw[0].dest_pal   =   0x05000000+0x200;
            hblank_proc->draw[0].func = hblank_draw0;

            //如果只有一个超256色的头像,直接复制到目标
            int y = 0;
            gba_memset(hblank_proc->lines,0,sizeof(hblank_proc->lines));
            for(y=0;y<80;y++){
                if(d_linepal[y]){
                    hblank_proc->lines[y].pal_addr = 0x05000000+0x200;
                    hblank_proc->lines[y].pal_src = d_linepal[y];
                    hblank_proc->lines[y].pal_num = 64*2;
                }
            }
        }
        else{
            uint8_t **d_linepal2 = linepal;
            uint8_t *d_pal2 = draw_pal;
            uint8_t *pal_ptr = 0x0600d000; //调色板放在VRAM里
            //需要判断每一行
            gba_memset(hblank_proc->lines,0,sizeof(hblank_proc->lines));
            for(y=0;y<80;y++){
                if(d_linepal[y]&&d_linepal2[y]){
                    //合并调色板
                    hblank_proc->lines[y].pal_addr = 0x05000000+0x200;
                    hblank_proc->lines[y].pal_src = pal_ptr;
                    hblank_proc->lines[y].pal_num = 2*64*2;
                    gba_memcpy(pal_ptr,d_linepal2[y],64*2);
                    pal_ptr += 64*2;
                    gba_memcpy(pal_ptr,d_linepal[y],64*2);
                    pal_ptr += 64*2;
                }
                else if(d_linepal[y]){
                    //设置更新目标调色板1
                    hblank_proc->lines[y].pal_addr = 0x05000000+0x200+ 0x40 * 2;
                    hblank_proc->lines[y].pal_src = d_linepal[y];
                    hblank_proc->lines[y].pal_num = 64*2;
                }
                else if(d_linepal2[y]){
                    //设置更新目标调色板2
                    hblank_proc->lines[y].pal_addr = 0x05000000+0x200 ;
                    hblank_proc->lines[y].pal_src = d_linepal2[y];
                    hblank_proc->lines[y].pal_num = 64*2;
                }
            }
        }
    }
       //为0x6b
    #endif
}

static void clear(){
    hblank_proc->count++;
}

const uint32_t rom85B8EEC[] = {
    1, 0x80DC3F4,
    8, 0x85C29C8,
    0xE, 0,
    #if NHACK
    2, 0x800549D,   //把头像的tile数据传送到tile层
    2, 0x80054C5,   //设置精灵数据
    3, 0x80054C5,   //设置精灵数据
    #else
    2, h800549D,   //把头像的tile数据传送到tile层
    2, h80054C5,   //设置精灵数据
    3, h80054C5,   //
    //2,clear,
    #endif
    0,0,
};

static void nullfunc(){
}

int _8005544_hack(uint32_t a1,uint32_t a2,int16_t a3,int16_t a4,int a5){
    if(!hblank_proc->draw[0].func){
        hblank_proc->draw[0].func = nullfunc;
    }
    if(!hblank_proc->draw[1].func){
        hblank_proc->draw[1].func = nullfunc;
    }
    if(!hblank_proc->draw[2].func){
        hblank_proc->draw[2].func = nullfunc;
    }
    if(!hblank_proc->draw[3].func){
        hblank_proc->draw[3].func = nullfunc;
    }
    if(*(uint32_t*)(0x3004920+a1*4)){
        return 0;
    }
    else{
        uint32_t event = //CALLT(0x8002BCC,0x85b8eec,5);
            CALLT(0x8002BCC,rom85B8EEC,5);
        *(uint32_t*)(0x3004920+a1*4) = event;
        uint32_t *v = CALLT(0x800541c,a2);
        if(a5&0x2000){
            int zero = 0;
            //设置头像调色板
            CpuFastSet(&zero,
            geth(0x202A688+4+a1*8)*0x20 + 0x2022AA8,
            0x1000008
            );
            CALLT(0x8001EE4);
            //0x2022b68,对象的调色板,会实现渐变效果
        }
        else{
            //设置头像调色板
            CALLT(0x8000D68,v[2],
            (geth(0x202A688+4+a1*8)+ 0x10)*0x20 ,
            32
            );
        }

        str(event+0x2c,v);
        strb(event+0x40,a1);
        strh(event+0x3e,a2);
        strb(event+0x41,5);
        strh(event+0x34,a3);
        strh(event+0x36,a4);
        if((a5&0x1000)){
            str(event+0x44,0);
            str(event+0x48,0);
        }
        else{
            //str(event+0x44,CALLT(0x8002bcc,0x85b8fe4,event));
            //str(event+0x48,CALLT(0x8002bcc,0x85b8ffc,event));
        }
        str(event+0x30,~a5);
        CALLT(0x8005678,event,a5,0); //设置精灵属性的数据
        //gba_memcpy(hblank_proc->exec,hblank,(uint32_t)hblank_end - (uint32_t)hblank + 0x500);
        irqSet(IRQ_HBLANK,hblank);
        irqEnable(IRQ_HBLANK);
        return event;
    }
}

int _8005548_r7(){
    nasm("mov r0,r0")
    nasm("JMP8005548_r7:")
    nasm("ldr r4,[sp,#4*4]")
    nasm("mov lr,r4")
    nasm("pop {r4,r5,r6,r7}")
    nasm("add sp,sp,#4")
    nasm("b _8005544_hack");
}
